package com.sorhis.service.impl;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.collection.CollectionUtil;
import cn.hutool.core.lang.Assert;
import cn.hutool.core.util.ObjectUtil;
import cn.hutool.core.util.StrUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.sorhis.common.constant.Constants;
import com.sorhis.common.enums.MenuType;
import com.sorhis.dto.SysMenuDTO;
import com.sorhis.entity.SysMenu;
import com.sorhis.entity.SysRole;
import com.sorhis.mapper.SysMenuMapper;
import com.sorhis.service.ISysMenuService;
import com.sorhis.utils.DozerUtil;
import com.sorhis.utils.Tools;
import com.sorhis.vo.*;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.*;
import java.util.stream.Collectors;

/**
 * <p>
 *  服务实现类
 * </p>
 *
 * @author xihao.ding
 * @since 2025-02-10
 */
@Service
public class SysMenuServiceImpl extends ServiceImpl<SysMenuMapper, SysMenu> implements ISysMenuService {

    @Override
    public List<SysMenuTreeVO> tree(SysMenuDTO sysMenuDTO) {
        List<SysMenuTreeVO> result = new ArrayList<>();
        List<SysMenu> list = this.list(new QueryWrapper<SysMenu>().ne("menu_type", 3)
                .orderByAsc("menu_sort"));
        for(SysMenu sysMenus : list){
            SysMenuTreeVO sysMenuTreeVO = new SysMenuTreeVO();
            sysMenuTreeVO.setId(sysMenus.getId());
            sysMenuTreeVO.setMenuName(sysMenus.getMenuName());
            sysMenuTreeVO.setParentId(sysMenus.getParentId());
            result.add(sysMenuTreeVO);
        }
        return Tools.recursionForMenuTree(result, Constants.DEFAULT_ID);
    }

    @Override
    @Transactional
    public Boolean saveOrUpateDomain(SysMenuDTO sysMenuDTO) {
        SysMenu sysMenu = new SysMenu();
        BeanUtil.copyProperties(sysMenuDTO , sysMenu);
        return this.saveOrUpdate(sysMenu);
    }

    @Override
    @Transactional
    public Boolean del(String id) {
        LambdaUpdateWrapper<SysMenu> updateWrapper = new LambdaUpdateWrapper<>();
        Assert.notEmpty(id , "ID不能为空");
        updateWrapper.eq(SysMenu::getId , id);
        updateWrapper.set(SysMenu::getDeleted , 1);
        return this.update(updateWrapper);
    }

    @Override
    public List<SysMenuTableVO> listTable(SysMenuDTO sysMenuDTO) {
        //查询所有菜单
        List<SysMenu> list = this.list(new LambdaQueryWrapper<SysMenu>()
                .eq(ObjectUtil.isNotNull(sysMenuDTO.getIuse()), SysMenu::getIuse , sysMenuDTO.getIuse())
                .like( StrUtil.isNotBlank( sysMenuDTO.getMenuName()),SysMenu::getMenuName, sysMenuDTO.getMenuName())
                .orderByAsc(SysMenu::getMenuSort));
        if(CollectionUtil.isEmpty(list)){
           return new ArrayList<>();
        }
        List<SysMenuTableVO> sysMenuListVOS = DozerUtil.mapList(list, SysMenuTableVO.class);
        List<SysMenuTableVO> hasNotParentItem = new ArrayList<>();

        // 初始化一个HashMap，用于存储ID与SysMenuTableVO对象之间的映射关系
        Map<String, SysMenuTableVO> map = new HashMap<>();
        // 遍历SysMenuTableVO对象的列表，为每个菜单项创建一个空的子菜单列表，并将其存储到映射中
        for (SysMenuTableVO sysMenuListVO : sysMenuListVOS) {
            // 为每个菜单项初始化一个空的子菜单列表，确保每个菜单项都有一个可以添加子菜单的地方
            sysMenuListVO.setChildren(new ArrayList<>());
            // 将菜单项的ID与其本身作为键值对存入映射中，便于后续根据ID快速查找菜单项
            map.put(sysMenuListVO.getId(), sysMenuListVO);
        }

        // 遍历菜单项列表，以构建菜单树结构
        for (SysMenuTableVO sysMenuTableVO : sysMenuListVOS) {
            // 根据当前菜单项的父ID获取其父菜单项
            SysMenuTableVO parentItem = map.get(sysMenuTableVO.getParentId());
            if (parentItem != null) {
                // 如果父菜单项存在，则将当前菜单项添加到父菜单项的子菜单列表中
                parentItem.getChildren().add(sysMenuTableVO);
            } else if (!sysMenuTableVO.getParentId().equals(Constants.DEFAULT_ID)) {
                // 如果父菜单项不存在且当前菜单项的父ID不是默认值，则将当前菜单项添加到无父菜单项列表中
                hasNotParentItem.add(sysMenuTableVO);
            }
        }
        // 筛选出父菜单ID为DEFAULT_ID的所有菜单项，并收集到一个新的列表中
        List<SysMenuTableVO> res = sysMenuListVOS.stream().filter(item -> Constants.DEFAULT_ID.equals(item.getParentId())).collect(Collectors.toList());
        // 将没有父菜单项的列表添加到筛选后的列表中，以合并结果
        res.addAll(hasNotParentItem);
        return res;
    }

    @Override
    public Map<String, Object> getMenusByUserId(String userId) {
        Map<String , Object> map = new HashMap();
        List<MenuRouterVO> menuList = new ArrayList();
        List<String> authCode = new ArrayList();
        map.put("authCode" , authCode);
        map.put("menuList" , menuList);
        List<SysMenu> sysMenus = null;
        // 内置账号
        if(StrUtil.isBlank(userId)){
            sysMenus = this.list(new LambdaQueryWrapper<SysMenu>().orderByAsc(SysMenu::getMenuSort));
        }else{
            //所有菜单
            sysMenus = this.getBaseMapper().menusByUserId(userId);
        }
        //过滤出按钮菜单
        List<SysMenu>  buttonMenusList = sysMenus.stream().filter(e -> e.getMenuType() == MenuType.THREE.getCode()).collect(Collectors.toList());
        List<String> buttons = buttonMenusList.stream().map(e-> e.getAuthCode()).collect(Collectors.toList());
        authCode.addAll(buttons);
        //排除按钮的菜单
        List<SysMenu> menus = sysMenus.stream().filter(e -> e.getMenuType() != MenuType.THREE.getCode()).collect(Collectors.toList());
        menuList.addAll(this.recursion(menus , Constants.DEFAULT_ID));
        return map;
    }


    private List<SysMenuTableVO> getChildrenMenus(String parentId , List<SysMenuTableVO> allList) {
        return    allList.stream()
                .filter(tenant -> parentId.equals(tenant.getParentId()))
                .peek(tenant -> tenant.setChildren(getChildrenMenus( tenant.getId(),allList)))
                .collect(Collectors.toList());
    }

    // 递归
    public List<MenuRouterVO> recursion(List<SysMenu> lists, String parentId) {
        List<MenuRouterVO> result = new ArrayList<>();
        for (SysMenu sysMenus : lists) {
            if (sysMenus.getParentId().equals(parentId)) {
                MenuRouterVO sysMenusVO = new MenuRouterVO();
                sysMenusVO.setPath(sysMenus.getMenuPath() == null ? "" : sysMenus.getMenuPath());
                sysMenusVO.setName(sysMenus.getMenuModuleName() == null ? "" : sysMenus.getMenuModuleName());
                sysMenusVO.setRedirect(sysMenus.getRedirect() == null ? "" : sysMenus.getRedirect());
                sysMenusVO.setComponent(sysMenus.getMenuModuleLocation() == null ? "" : sysMenus.getMenuModuleLocation());

                MetaRouterVO metaRouterVO = new MetaRouterVO();
                metaRouterVO.setTitle(sysMenus.getMenuName() == null ? "" : sysMenus.getMenuName());
                metaRouterVO.setIcon(sysMenus.getMenuIcon() == null ? "" : sysMenus.getMenuIcon());
                metaRouterVO.setCache(sysMenus.getCache() == Constants.YES);
                metaRouterVO.setHidden(sysMenus.getMenuShow() == Constants.NO);
                sysMenusVO.setMeta(metaRouterVO); //组件名称
                List<MenuRouterVO> array = recursion(lists, sysMenus.getId());
                if (array.size() != 0) {
                    sysMenusVO.setChildren(array);
                }
                result.add(sysMenusVO);
            }
        }
        return result;
    }


}
